package controller;

/*
 * Action for researchers to input question for the questionnaire.
 * Used by both Binary and Network Binary type questions.
 */

import formbeans.MultipleChoiceForm;
import helper.EntityAttributeType;
import helper.MultipleChoiceType;
import helper.QuestionType;
import helper.UserType;

import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.mybeans.dao.DAOException;
import org.mybeans.form.FormBeanException;
import org.mybeans.form.FormBeanFactory;

import databeans.EntityClass;
import databeans.MultipleChoiceq;
import databeans.Question;
import databeans.Survey;
import databeans.User;
import model.EntityClassDAO;
import model.EntityDAO;
import model.MultipleChoiceqDAO;
import model.Model;
import model.QuestionDAO;

public class MultipleChoiceqAction extends Action {
	private FormBeanFactory<MultipleChoiceForm> mcformBeanFactory = FormBeanFactory.getInstance(MultipleChoiceForm.class);
	private MultipleChoiceqDAO mcDAO;
	private QuestionDAO questionDAO;
	private EntityClassDAO ecDAO;
	private EntityDAO entityDAO;
	
	public MultipleChoiceqAction(Model model) {
		mcDAO = model.getMultipleChoiceqDAO();
		questionDAO = model.getQuestionDAO();
		ecDAO = model.getEntityClassDAO();
		entityDAO = model.getEntityDAO();
	}
	
    public String getName() {
		return "multiplechoiceq.do";
	}
    
    public String perform(HttpServletRequest request) {

        List<String> errors = new ArrayList<String>();
        request.setAttribute("errors",errors);
        
    	// First, validate whether researcher is accessing this
    	HttpSession session = request.getSession(false);
    	User user = (User) session.getAttribute("user");
    	
    	if (user.getType() != UserType.RESEARCHER) {
    		errors.add("You are not a researcher!");
    		return "homepage.jsp";
    	}
    	
    	// Validate the question number
    	Question question = (Question) session.getAttribute("question");
    	if (question == null) {
    		errors.add("Invalid question number");
    		return "createsurvey.jsp";
    	}
    	
    	Survey survey = (Survey) session.getAttribute("survey");
    	
		String button = request.getParameter("button");
		
		if (button == null)
			return "multiplechoiceq.jsp";
		
		if (button.equals("Back")) {
			synchronized(session) {
				session.setAttribute("question", null);
			}
			return "createsurvey.jsp";
		}
		
		if (button.equals("Import Entity Data")) {
			synchronized(session) {
				session.setAttribute("pageFrom", "multiplechoiceq.jsp");
				session.setAttribute("importentitybody", "init");
			}
			return "importentity.jsp";
		}

		if (button.equals("Submit") || button.equals("Next")) {
	        try {
	        	int num = Integer.parseInt((String) session.getAttribute("multiplechoice"));
	        	boolean network = Boolean.parseBoolean((String) session.getAttribute("network"));
	        	
	        	if (num == 1) {
	        		MultipleChoiceForm form = mcformBeanFactory.create(request);
	            	request.setAttribute("mcform",form);
	            	
	            	if (!form.isPresent()) {
	            		return "multiplechoiceq.jsp";
	            	}
	            	
	        		// Validate for errors in the form
	            	if (network)
	            		errors.addAll(form.checkMultipleChoiceFormErrorsNetwork());
	            	else
	            		errors.addAll(form.checkMultipleChoiceFormErrors());
	        		if (errors.size() != 0) {
	        			return "multiplechoiceq.jsp";
	        		}
	        		
	        		question.setQuestion(form.getQuestion());
	        		question.setDynetmlAttr(form.getDynetmlAttr());
	        		
	        		if (network) { // Network Weighted List / Network Rank Order Question
	        			question.setEntityFrom("Respondents");
	        			question.setEntityTo(form.getClassName());
	        			question.setDynetmlType(-1);
	        			questionDAO.updateEntityToFrom(question, ecDAO);
	        		}
	        		
	        		questionDAO.updateQuestion(question);
	        		synchronized(session) {
	        			session.setAttribute("question", question);
	        			if (question.getType() != QuestionType.NETWORK_RANK_ORDER)
	        				session.setAttribute("multiplechoice", form.getNum());
	        			else {
	        				EntityClass ec = ecDAO.lookupBySidName(survey.getSid(), form.getClassName());
	        				session.setAttribute("numEntity", entityDAO.sizeByEcid(ec.getEcid()));
	        				session.setAttribute("multiplechoice", "3");
	        			}
	        		}
	        		
        			return "multiplechoiceq.jsp";
	        	}
	        	else {
	        		// No formbean for this case, formbean impossible
	        		if (question.getType() == QuestionType.NETWORK_WEIGHTED) { // Network Weighted List
	        			try {
	        				// Check for errors
			        		for (int i = 1; i <= num; i++) {
			        			String desc = request.getParameter("choice"+i+"desc");
			        			String weightStr = request.getParameter("choice"+i+"num");
			        			if (desc == null || weightStr == null) { // Check for empty fields
			        				errors.add("Please enter all fields.");
			        				return "multiplechoiceq.jsp";
			        			}
			        			Integer.parseInt(weightStr); // Check if weight is integer
			        		}
			        		
			        		for (int i = 1; i <= num; i++) {
			        			String desc = request.getParameter("choice"+i+"desc");
			        			String weightStr = request.getParameter("choice"+i+"num");
			        			MultipleChoiceq mcq = new MultipleChoiceq(question.getQid(), i);
			        			mcq.setType(MultipleChoiceType.NETWORK_WEIGHTED);
			        			mcq.setChoiceDesc(desc);
			        			mcq.setWeight(Integer.parseInt(weightStr));
			        			mcDAO.create(mcq, questionDAO);
			        		}
	        			} catch (NumberFormatException e) {
	        				errors.add("A number should be entered for the weight field.");
	        				return "multiplechoiceq.jsp";
	        			}
	        		}
	        		else if (question.getType() == QuestionType.NETWORK_RANK_ORDER) { // Network Rank Order
	        			try {
	        				String result = request.getParameter("numRank");
	        				int resultInt = Integer.parseInt(result);
	        				int numEntity = (Integer) session.getAttribute("numEntity");
	        				if (resultInt < 1 || resultInt > numEntity) {
	        					errors.add("Number should be at least 1 and at most the number of entities.");
	        					return "multiplechoiceq.jsp";
	        				}
	        				synchronized(session) {
	        					session.removeAttribute("numEntity");
	        				}
	        				MultipleChoiceq mcq = new MultipleChoiceq(question.getQid(), resultInt);
	        				mcq.setType(MultipleChoiceType.NETWORK_RANK_ORDER);
	        				mcq.setChoiceDesc("Number of Rank Order");
	        				mcDAO.create(mcq, questionDAO);
	        			} catch (NumberFormatException e) {
	        				errors.add("A number should be entered.");
	        				return "multiplechoiceq.jsp";
	        			}
	        		}
	        		else { // Only check and update for Non-network Multiple Choice / Selection / Rank Order Questions
		        		// Check for errors (empty fields)
		        		for (int i = 1; i <= num; i++) {
		        			if (request.getParameter("choice"+i) == null) {
		        				errors.add("Please enter all fields.");
		        				return "multiplechoiceq.jsp";
		        			}
		        		}
		        		
		        		int type;
		        		if (question.getType() == QuestionType.MULTIPLE_CHOICE)
		        			type = MultipleChoiceType.MULTIPLE_CHOICE;
		        		else if (question.getType() == QuestionType.MULTIPLE_SELECTION)
		        			type = MultipleChoiceType.MULTIPLE_SELECTION;
		        		else
		        			type = MultipleChoiceType.RANK_ORDER;
		        		
		        		// Only check for all number fields for Multiple Choice Questions
		        		if (type == MultipleChoiceType.MULTIPLE_CHOICE) {
			        		try {
			        			for (int i = 1; i <= num; i++)
			        				Integer.parseInt(request.getParameter("choice"+i));
			        			
			        			question.setDynetmlType(EntityAttributeType.CATEGORY_NUMBER);
			        		} catch (NumberFormatException e) {
			        			question.setDynetmlType(EntityAttributeType.CATEGORY_TEXT);
			        		}
		        		}
		        		else
		        			question.setDynetmlType(EntityAttributeType.TEXT);
		        		
		        		questionDAO.updateQuestion(question);
		        		synchronized(session) {
		        			session.setAttribute("question", question);
		        		}
		        		for (int i = 1; i <= num; i++) {
		        			MultipleChoiceq mcq = new MultipleChoiceq(question.getQid(), i);
		        			mcq.setType(type);
		        			mcq.setChoiceDesc((String) request.getParameter("choice"+i));
			        		mcDAO.create(mcq, questionDAO);
		        		}
	        		}
	        		
	        		synchronized(session) {
	        			session.removeAttribute("multiplechoice");
	        		}
	        		
	        		Question[] questionlist = questionDAO.getQuestionBySidSortedQnum(question.getSid(), true);
	    			synchronized(session) {
	    				session.setAttribute("questionlist", questionlist);
	    			}
	        		return "surveysummary.jsp";
	        	}
	        } catch (DAOException e) {
	        	errors.add(e.getMessage());
	        	return "errors.jsp";
	        } catch (FormBeanException e) {
	        	errors.add(e.getMessage());
	        	return "errors.jsp";
	        }
        }
        errors.add("Illegal button value of " + button);
		return "errors.jsp";
    }
}
